package com.jeasonzhao.commons.xml;

import java.util.Map;
import java.util.Vector;

import com.jeasonzhao.commons.parser.expression.CSSParser;
import com.jeasonzhao.commons.parser.expression.SyntaxException;
import com.jeasonzhao.commons.parser.lex.LexException;
import com.jeasonzhao.commons.utils.Algorithms;

public class HTMLNode extends XMLNode
{
    protected static final long serialVersionUID = 1L;
    private Vector<XMLAttribute> m_styles = null;
    public HTMLNode()
    {
        super();
    }

    public HTMLNode(String nodeName)
    {
        super(nodeName);
    }

    public HTMLNode setCssName(String str)
    {
        this.addAttribute("class",str);
        return this;
    }

    public HTMLNode setControlName(String str)
    {
        this.addAttribute("name",str);
        this.addAttribute("id",str);
        return this;
    }

    private XMLAttribute styleNode(String strName)
    {
        if(null == m_styles || Algorithms.isEmpty(strName))
        {
            m_styles = new Vector<XMLAttribute>();
        }
        for(XMLAttribute a : m_styles)
        {
            if(null != a && a.getName().equalsIgnoreCase(strName))
            {
                return a;
            }
        }
        XMLAttribute ax = new XMLAttribute(strName,null);
        m_styles.add(ax);
        return ax;
    }

    public Vector<XMLAttribute> getStyles()
    {
        return m_styles;
    }

    public void hide()
    {
        this.setStyle("display","none");
    }

    public String styleOf(String ...names)
    {
        if(null == names || this.m_styles == null)
        {
            return null;
        }
        for(String str : names)
        {
            if(str != null)
            {
                for(XMLAttribute a : m_styles)
                {
                    if(a != null && a.getName() != null && a.getName().equalsIgnoreCase(str.trim()))
                    {
                        return a.getValue();
                    }
                }
            }
        }
        return null;
    }

    public HTMLNode setStyle(Object ...params)
    {
        if(null == this.m_styles)
        {
            this.m_styles = new Vector<XMLAttribute>();
        }
        for(int n = 0;null != params && n < params.length;n += 2)
        {
            if((n + 1) < params.length
               && null != params[n]
               && null != params[n + 1])
            {
                this.styleNode(params[n].toString().trim()).setValue(params[n + 1]);
            }
        }
        return this;
    }

    public String toHtml(boolean includSubNodesHtml)
    {
        generateStyleAttribute();
        return super.toHtml(includSubNodesHtml);
    }

    public String toString()
    {
        return this.toHtml();
    }
    protected void prepareBeforeToHtml()
    {
        generateStyleAttribute();
    }

    protected String wrapAttributeValue(Object obj)
    {
        String str = Algorithms.toString(obj);
        return str.replaceAll("\"","\\\\\"");
    }

    private void generateStyleAttribute()
    {
        if(null!=this.getName())
        {
            this.setName(this.getName().toLowerCase());
        }
        if(null != this.m_styles && this.m_styles.size() > 0)
        {
            StringBuffer buf = new StringBuffer();
            for(XMLAttribute a : this.m_styles)
            {
                if(a != null
                   && false == Algorithms.isEmpty(a.getName())
                   && false == Algorithms.isEmpty(a.getValue())
                    )
                {
                    buf.append(a.getName())
                        .append(':')
                        .append(Algorithms.toString(a.getValue()))
                        .append(';');
                }
            }
            if(buf.length() > 0)
            {
                XMLAttribute attr = this.selectAttribute("style");
                if(null == attr)
                {
                    this.addAttribute("style",buf.toString());
                }
                else
                {
                    attr.setValue(buf.toString());
                }
            }
        }
    }

    public void setStyleFromString(String pas)
        throws SyntaxException,LexException
    {
        if(null == pas)
        {
            return;
        }
        java.util.Hashtable<String,String> hash = CSSParser.parsePart(pas);
        for(Map.Entry<String,String> e : hash.entrySet())
        {
            this.setStyle(e.getKey(),e.getValue());
        }
    }

    public static class DIV extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public DIV()
        {
            super("DIV");
        }

        public DIV(String strId)
        {
            super("DIV");
            this.addAttribute("id",strId);
        }
    }

    public static class DIVClearFloat extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public DIVClearFloat()
        {
            super("DIV");
            this.setStyle("clear","both");
            this.setInnerText("");
        }
    }

    public static class IMG extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public IMG(String strId)
        {
            super("IMG");
            this.addAttribute("id",strId);
        }
    }

    public static class SPAN extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public SPAN()
        {
            super("SPAN");
        }
    }

    public static class TABLE extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public TABLE(String strId)
        {
            super("TABLE");
            this.addAttribute("id",strId);
        }

        public XMLNode getBodyNode()
        {
            return addNonExistedNode("tbody");
        }

        public XMLNode getHeaderNode()
        {
            return addNonExistedNode("thead");
        }

        public XMLNode getFooterNode()
        {
            return addNonExistedNode("tfooter");
        }

        public TABLE addHeaderRow(String ...args)
        {
            if(null == args)
            {
                return this;
            }
            XMLNode nodeheader = this.getHeaderNode().addNode("tr");
            for(String str : args)
            {
                nodeheader.addNode("td").setInnerText(str);
            }
            return this;
        }

        public TABLE addRow(String ...args)
        {
            if(null == args)
            {
                return this;
            }
            XMLNode nodeheader = this.getBodyNode().addNode("tr");
            for(String str : args)
            {
                nodeheader.addNode("td").setInnerText(str);
            }
            return this;
        }

        public TABLE addFooterRow(String ...args)
        {
            if(null == args)
            {
                return this;
            }
            XMLNode nodeheader = this.getFooterNode().addNode("tr");
            for(String str : args)
            {
                nodeheader.addNode("td").setInnerText(str);
            }
            return this;
        }

        public XMLNode newRow()
        {
            return this.getFooterNode().addNode("tr");
        }
    }

    public static class SELECT extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public SELECT()
        {
            super("SELECT");
        }

        public SELECT addOption(String id,String name)
        {
            HTMLNode node = new HTMLNode("option");
            node.addAttribute("value",id)
                .setInnerText(name);
            this.addNode(node);
            return this;
        }
    }

    public static class LI extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public LI(String strContent)
        {
            super("LI");
            this.setInnerText(strContent);
        }
    }

    public static class A extends XMLNode
    {
        private static final long serialVersionUID = 1L;
        public A(String strUrl,String strContent)
        {
            super("A");
            this.setInnerText(strContent);
            this.addAttribute("href",strUrl);
        }
    }

    public static class SCRIPT extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public SCRIPT(String strUrl)
        {
            super("script");
            this.addAttribute("type","text/javascript");
            this.addAttribute("src",strUrl);
        }
    }

    public static class INPUT extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public INPUT()
        {
            super("input");
        }

        public INPUT(String strname,String strValue)
        {
            super("input");
            this.addAttribute("type","text")
                .addAttribute("name",strname)
                .addAttribute("id",strname)
                .addAttribute("value",strValue);
        }
    }

    public static class HIDDEN extends INPUT
    {
        private static final long serialVersionUID = 1L;
        public HIDDEN()
        {
            super();
        }

        public HIDDEN(String strname,String strValue)
        {
            super();
            this.addAttribute("type","hidden")
                .addAttribute("name",strname)
                .addAttribute("id",strname)
                .addAttribute("value",strValue);
        }
    }

    public static class P extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public P()
        {
            super("p");
        }

        public P(String strContent)
        {
            super("p");
            this.setInnerText(strContent);
        }
    }

    public static class BR extends HTMLNode
    {
        private static final long serialVersionUID = 1L;
        public BR()
        {
            super("br");
        }
    }

}
